package io.github.jieblog.juc.day2;

import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * Created by jie on 2017/3/13.
 * 比较值 和 时间戳 状态
 */
public class AtomicStampedReferenceDemo {
    private static AtomicStampedReference<Integer> money = new AtomicStampedReference<Integer>(19, 0);

    /**
     * 消费
     */
    static class TaskConsumer implements Runnable {

        @Override
        public void run() {
            int stamped = money.getStamp();
            Integer m = money.getReference();
            if (money.compareAndSet(m, m - 10, stamped, stamped + 1)) {
                System.out.println("消费10元");
            }
        }
    }

    /**
     * 生产
     */
    static class TaskProvider implements Runnable {

        @Override
        public void run() {
            int stamped = money.getStamp();
            Integer m = money.getReference();
            if (money.compareAndSet(m, m + 20, stamped, stamped + 1)) {
                System.out.println("充值成功,余额 ->" + money.getReference());
            } else {
                System.out.println("充值失败,余额 ->" + money.getReference());
            }
        }
    }

    /**
     * 发生充值失败的情况。 时间戳大于 期待时间戳，解决多线程下 充值一次 + 20 然后消费两次以后-20 然后余额一致 还能充值成功的情况。
     *
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        TaskConsumer consumer = new TaskConsumer();
        TaskProvider provider = new TaskProvider();

        Thread[] consumers = new Thread[1000];
        Thread[] providers = new Thread[1000];

        for (int i = 0; i < 1000; i++) {
            consumers[i] = new Thread(consumer);
        }

        for (int i = 0; i < 1000; i++) {
            providers[i] = new Thread(provider);
        }

        for (int i = 0; i < 1000; i++) {
            consumers[i].start();
            providers[i].start();
            consumers[i].join();
            providers[i].join();
        }
    }
}
